home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 33.6 KB | 1,061 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWScrolr.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFrameW.hpp"
-
- #ifndef FWSCROLR_H
- #include "FWScrolr.h"
- #endif
-
- #ifndef FWPART_H
- #include "FWPart.h"
- #endif
-
- #ifndef FWFRAME_H
- #include "FWFrame.h"
- #endif
-
- #ifndef FWSCLNOT_H
- #include "FWSclNot.h"
- #endif
-
- #ifndef FWITERS_H
- #include "FWIters.h"
- #endif
-
- #ifndef FWUTIL_H
- #include "FWUtil.h"
- #endif
-
- #ifndef FWSCLBAR_H
- #include "FWSclBar.h"
- #endif
-
- #ifndef FWNOTDEF_H
- #include "FWNotDef.h"
- #endif
-
- #ifndef FWCONTXT_H
- #include "FWContxt.h"
- #endif
-
- #ifndef FWEVEDEF_H
- #include "FWEveDef.h"
- #endif
-
- // ----- OS Layer -----
-
- #ifndef FWODGEOM_H
- #include "FWODGeom.h"
- #endif
-
- #ifndef SLMIXOS_H
- #include "SLMixOS.h"
- #endif
-
- #ifndef SLREGION_H
- #include "SLRegion.h"
- #endif
-
- // ----- Foundation Layer -----
-
- #ifndef FWAROPER_H
- #include "FWArOper.h"
- #endif
-
- #ifndef FWSOMENV_H
- #include "FWSOMEnv.h"
- #endif
-
- // ----- OpenDoc Includes -----
-
- #ifndef SOM_ODFacet_xh
- #include <Facet.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef SOM_ODTransform_xh
- #include <Trnsform.xh>
- #endif
-
- #ifndef SOM_ODWindow_xh
- #include <Window.xh>
- #endif
-
- //========================================================================================
- // RunTime Info
- //========================================================================================
-
- #ifdef FW_BUILD_MAC
- #pragma segment FW_FrameSegment
- #endif
-
- //========================================================================================
- // Constant
- //========================================================================================
-
- const FW_Fixed FW_kStdScrollUnit = FW_IntToFixed(16);
-
- //========================================================================================
- // CLASS FW_CPrivBaseScroller
- //========================================================================================
-
- FW_DEFINE_CLASS_M0(FW_CPrivBaseScroller)
-
- // This class is archivable, but we provide the archiving implementation in a separate
- // translation unit in order to enable deadstripping of the archiving-related code
- // in parts that do not use archiving with this class.
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBaseScroller::FW_CPrivBaseScroller
- //----------------------------------------------------------------------------------------
-
- FW_CPrivBaseScroller::FW_CPrivBaseScroller() :
- fHandlePageNavigationKeys(TRUE)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBaseScroller::~FW_CPrivBaseScroller
- //----------------------------------------------------------------------------------------
-
- FW_CPrivBaseScroller::~FW_CPrivBaseScroller()
- {
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CPrivBaseScroller::PrivCheckFrame
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivBaseScroller::PrivCheckFrame(Environment*) const
- {
- // Nothing to do. See FW_CScrollBarScroller::PrivCheckFrame
- }
- #endif
-
- //========================================================================================
- // CLASS FW_CScroller
- //========================================================================================
-
- FW_DEFINE_AUTO(FW_CScroller)
- FW_DEFINE_CLASS_M1(FW_CScroller, FW_CPrivBaseScroller)
-
- // This class is archivable, but we provide the archiving implementation in a separate
- // translation unit in order to enable deadstripping of the archiving-related code
- // in parts that do not use archiving with this class.
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::FW_CScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScroller::FW_CScroller(Environment* ev, FW_CFrame* frame) :
- FW_CPrivBaseScroller(),
- FW_MReceiver(),
- fFrame(frame),
- fAutoScrollInset(FW_IntToFixed(5)),
- fLastAutoScrollTick(0),
- fScrollUnit(FW_kStdScrollUnit, FW_kStdScrollUnit),
- fTranslation(FW_kZeroPoint),
- fMaxTranslation(FW_kZeroPoint)
- {
- FW_UNUSED(ev);
- FW_ASSERT(fFrame);
-
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::FW_CScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScroller::FW_CScroller(Environment* ev) :
- FW_CPrivBaseScroller(),
- FW_MReceiver(),
- fFrame(0),
- fAutoScrollInset(FW_IntToFixed(5)),
- fLastAutoScrollTick(0),
- fScrollUnit(FW_kStdScrollUnit, FW_kStdScrollUnit),
- fTranslation(FW_kZeroPoint),
- fMaxTranslation(FW_kZeroPoint)
- {
- FW_UNUSED(ev);
-
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::~FW_CScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScroller::~FW_CScroller()
- {
- FW_START_DESTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::RegisterScrollBar
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::RegisterScrollNotifier(Environment* ev, FW_MNotifier* notifier)
- {
- FW_UNUSED(ev);
- // create the interest for the scroll notification
- AddInterest(FW_CInterest(notifier, FW_kScrollMsg));
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::UnregisterScrollNotifier
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::UnregisterScrollNotifier(Environment* ev, FW_MNotifier* notifier)
- {
- FW_UNUSED(ev);
- FW_CInterest interest(notifier, FW_kScrollMsg);
- RemoveInterest(interest);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::TranslationToPixels
- //----------------------------------------------------------------------------------------
- // By default we use pixels. Override TranslationToPixels if your scroller units are for example
- // cells
- FW_CPoint FW_CScroller::TranslationToPixels(Environment* ev, const FW_CPoint& translation) const
- {
- FW_UNUSED(ev);
-
- return translation;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::HandleNotification
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::HandleNotification(Environment* ev, const FW_CNotification& notification)
- {
- if (notification.GetMessage() == FW_kScrollMsg)
- {
- const FW_CScrollNotification& scrollNfy = (FW_CScrollNotification&) notification;
-
- FW_CPoint oldPos = fTranslation;
-
- FW_XYSelector direction = scrollNfy.GetDirection(ev);
- fTranslation[direction] += scrollNfy.GetDelta(ev);
-
- PrivChangeFrameInternalTransform(ev, oldPos, fTranslation, direction, scrollNfy.ShouldScroll(ev));
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivScrollDraw
- //----------------------------------------------------------------------------------------
- // by is in pixels
-
- void FW_CScroller::PrivScrollDraw(Environment* ev, FW_Fixed by, FW_XYSelector direction)
- {
- FW_CAcquiredODTransform aqFrameInternal = fFrame->AcquireInternalTransform(ev);
-
- FW_CPoint scale;
- aqFrameInternal->GetScale(ev, (ODPoint*)&scale);
-
- FW_Wide wideBy[2];
- wideBy[FW_kHorizontal] = wideBy[FW_kVertical] = FW_IntToWide(0);
- wideBy[direction] = FW_WideMultiply(by, scale[direction]);
-
- #ifdef FW_BUILD_MAC
- FW_CAcquiredODWindow window = fFrame->AcquireODWindow(ev);
- ODPlatformWindow platformWindow = window->GetPlatformWindow(ev);
-
- GrafPtr port;
- ::GetPort(&port);
- ::SetPort(platformWindow);
- Point origin;
- origin.h = platformWindow->portRect.left;
- origin.v = platformWindow->portRect.top;
- ODRgnHandle clipRgn = ::FW_NewRegion();
- ::GetClip(clipRgn);
-
- ::SetOrigin(0, 0);
- #endif
-
- // ------ Scroll all Facets of the frame
- FW_CFrameFacetIterator ite(ev, fFrame);
- for (ODFacet* facet = ite.First(ev); ite.IsNotComplete(ev); facet = ite.Next(ev))
- {
- #ifdef FW_BUILD_MAC
- FW_CAcquiredODShape aqScrollShape = PrivCreateContentScrollShape(ev, direction);
-
- // converts to window coordinates
- FW_CAcquiredODTransform aqWindowFrameTransform = facet->AcquireWindowFrameTransform(ev, NULL);
- aqScrollShape->Transform(ev, aqWindowFrameTransform);
-
- FW_CPlatformRect platformRect = FW_GetShapeBoundingBox(ev, aqScrollShape);
-
- // get clip shape in window coordinates & intersect with scrollShape
- FW_CAcquiredODShape aqAggregateClipShape = FW_CopyAndRelease(ev, facet->AcquireAggregateClipShape(ev, NULL));
- aqAggregateClipShape->Transform(ev, aqWindowFrameTransform);
-
- aqAggregateClipShape->Intersect(ev, aqScrollShape);
-
- RgnHandle aggregateClipRgn = aqAggregateClipShape->GetQDRegion(ev);
- ::SetClip(aggregateClipRgn);
-
- RgnHandle invalidRgn = ::FW_NewRegion(); // will be adopted by aqInvalidShape. No need to dispose it
- ::ScrollRect(&platformRect, FW_WideToInt(wideBy[FW_kHorizontal]), FW_WideToInt(wideBy[FW_kVertical]), invalidRgn);
-
- FW_CAcquiredODShape aqInvalidShape = ::FW_NewODShape(ev, invalidRgn);
- aqInvalidShape->InverseTransform(ev, aqWindowFrameTransform);
-
- // ----- Update the facet -----
- facet->Invalidate(ev, aqInvalidShape, NULL);
- facet->GetWindow(ev)->Update(ev);
- #endif
-
- #ifdef FW_BUILD_WIN
- FW_DEBUG_MESSAGE("Needs to be redone");
- #endif
- }
-
- #ifdef FW_BUILD_MAC
- ::SetPort(platformWindow);
- ::SetClip(clipRgn);
- ::FW_DisposeRegion(clipRgn);
- ::SetOrigin(-origin.h, -origin.v);
- ::SetPort(port);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScaleBy
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::ScaleBy(Environment* ev, const FW_CPoint& scaling, FW_CGraphicContext* gc)
- {
- FW_ASSERT(scaling.x != FW_kFixed0 && scaling.y != FW_kFixed0);
-
- FW_CAcquiredODTransform aqInternal = fFrame->AcquireInternalTransform(ev);
- FW_CPoint contentLocation = fFrame->PrivGetContentViewOffset(ev);
-
- aqInternal->MoveBy(ev, (ODPoint*)&(-contentLocation));
-
- FW_CPoint prevScaling;
- aqInternal->GetScale(ev, (ODPoint*)&prevScaling);
- aqInternal->ScaleDownBy(ev, (ODPoint*)&prevScaling);
-
- aqInternal->ScaleBy(ev, (ODPoint*)&scaling);
- aqInternal->MoveBy(ev, (ODPoint*)&contentLocation);
-
- fFrame->PrivChangeInternalTransform(ev, aqInternal);
-
- UpdateScrollParameters(ev);
-
- if (gc)
- gc->Reset();
-
- fFrame->Invalidate(ev); // Invalidate the whole frame
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivChangeFrameInternalTransform
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::PrivChangeFrameInternalTransform(Environment* ev,
- const FW_CPoint& odlTranslation,
- const FW_CPoint& newTranslation,
- FW_XYSelector direction,
- FW_Boolean scroll)
- {
- FW_CAcquiredODTransform aqFrameInternal = fFrame->AcquireInternalTransform(ev);
-
- FW_CPoint scale;
- aqFrameInternal->GetScale(ev, (ODPoint*)&scale);
-
- FW_CPoint translation = -TranslationToPixels(ev, newTranslation);
-
- aqFrameInternal->SetOffset(ev, (ODPoint*)&translation);
-
- aqFrameInternal->ScaleBy(ev, (ODPoint*)&scale);
-
- // ----- Add the content view offset -----
- FW_CPoint temp = fFrame->PrivGetContentViewOffset(ev);
- aqFrameInternal->MoveBy(ev, (ODPoint*)&temp);
-
- fFrame->PrivChangeInternalTransform(ev, aqFrameInternal);
-
- if (scroll)
- {
- FW_CPoint offset = translation + TranslationToPixels(ev, odlTranslation);
- if (offset[direction] != FW_kFixed0)
- PrivScrollDraw(ev, offset[direction], direction);
- }
-
- // ----- Notify -----
- ScrollPositionChanged(ev, odlTranslation[direction], newTranslation[direction], direction);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::CalcMaxTranslation
- //----------------------------------------------------------------------------------------
- // By default the fMaxTranslation is equal to the extent minus the scrolling area size
-
- FW_Fixed FW_CScroller::CalcMaxTranslation(Environment* ev, FW_Fixed scrollingArea, FW_XYSelector direction)
- {
- FW_CPoint extent = fFrame->GetContentView(ev)->GetExtent(ev);
- return extent[direction] - scrollingArea;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivAdjustTranslations
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::PrivAdjustTranslations(Environment* ev,
- FW_XYSelector direction,
- FW_Fixed translation,
- FW_Fixed scrollingArea)
- {
- FW_UNUSED(ev);
-
- fTranslation[direction] = translation;
-
- // ----- calculate the maximum
- fMaxTranslation[direction] = CalcMaxTranslation(ev, scrollingArea, direction);
- if (fMaxTranslation[direction] < FW_kFixed0)
- fMaxTranslation[direction] = FW_kFixed0;
-
- // ----- Adjust the translation if necessary -----
- if (fTranslation[direction] > fMaxTranslation[direction])
- fTranslation[direction] = fMaxTranslation[direction];
-
- if (fTranslation[direction] < FW_kFixed0)
- fTranslation[direction] = FW_kFixed0;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::GetScrollingArea
- //----------------------------------------------------------------------------------------
- // GetScrollingArea returns the area in content coordinate of the content view
-
- FW_CRect FW_CScroller::GetScrollingArea(Environment* ev) const
- {
- return fFrame->GetContentView(ev)->GetBoundsInContent(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::UpdateScrollParameters
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::UpdateScrollParameters(Environment* ev)
- {
- FW_CRect boundsInContent = GetScrollingArea(ev);
-
- FW_CPoint oldPos(fTranslation);
- for (FW_XYSelector vhs = FW_kHorizontal; vhs <= FW_kVertical; ++vhs)
- {
- PrivAdjustTranslations(ev, vhs, boundsInContent[FW_kTopLeft][vhs], boundsInContent.Length(vhs));
- if (fTranslation[vhs] != oldPos[vhs])
- {
- FW_CAcquiredODShape tempShape = PrivCreateContentScrollShape(ev, vhs);
- fFrame->GetODFrame(ev)->Invalidate(ev, tempShape, NULL);
- PrivChangeFrameInternalTransform(ev, oldPos, fTranslation, vhs, FALSE);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScrollPositionChanged
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::ScrollPositionChanged(Environment* ev, FW_Fixed oldPos, FW_Fixed newPos, FW_XYSelector direction)
- {
- FW_UNUSED(ev);
- FW_UNUSED(oldPos);
- FW_UNUSED(newPos);
- FW_UNUSED(direction);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::InitializeAutoScroll
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::InitializeAutoScroll(Environment* ev)
- {
- FW_UNUSED(ev);
-
- fAutoScrollStage = kOutStage;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::GetPageUnit
- //----------------------------------------------------------------------------------------
-
- FW_Fixed FW_CScroller::GetPageUnit(Environment* ev, FW_XYSelector direction) const
- {
- FW_CRect boundsInContent = GetScrollingArea(ev);
- FW_Fixed pageUnit = boundsInContent.Length(direction) - fScrollUnit[direction];
- if (pageUnit < fScrollUnit[direction])
- pageUnit = fScrollUnit[direction];
- return pageUnit;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivLimitScrolling
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::PrivLimitScrolling(FW_CPoint& scrollBy) const
- {
- for (FW_XYSelector vhs = FW_kHorizontal; vhs <= FW_kVertical; ++vhs)
- {
- if (fTranslation[vhs] + scrollBy[vhs] > fMaxTranslation[vhs])
- scrollBy[vhs] = fMaxTranslation[vhs] - fTranslation[vhs];
- else if (fTranslation[vhs] + scrollBy[vhs] < FW_kFixed0)
- scrollBy[vhs] = - fTranslation[vhs];
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivRealignScroller
- //----------------------------------------------------------------------------------------
- // PrivRealignScroller doesn't notify anybody. Just Changes the fTranslation field
-
- void FW_CScroller::PrivRealignScroller(Environment* ev)
- {
- FW_CRect boundsInContent = GetScrollingArea(ev);
-
- for (FW_XYSelector vhs = FW_kHorizontal; vhs <= FW_kVertical; ++vhs)
- PrivAdjustTranslations(ev,
- vhs,
- boundsInContent[FW_kTopLeft][vhs],
- boundsInContent.Length(vhs));
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::AutoScrollOffset
- //----------------------------------------------------------------------------------------
-
- FW_CPoint FW_CScroller::AutoScrollOffset(Environment* ev,
- const FW_CPoint& currentPoint,
- unsigned long delay)
- {
- FW_CPoint scroll(FW_kZeroPoint);
-
- if (fScrollUnit != FW_kZeroPoint)
- {
- FW_CPoint delta;
-
- FW_CRect content = fFrame->GetContentView(ev)->GetBoundsInContent(ev);
-
- FW_CRect bounds(content);
-
- bounds.Inset(fAutoScrollInset);
-
- switch (::FW_RegionCode(currentPoint, bounds))
- {
- case 9:
- scroll = -fScrollUnit;
- delta.x = currentPoint.x - content.left;
- delta.y = currentPoint.y - content.top;
- break;
- case 1:
- scroll.y = -fScrollUnit.y;
- delta.y = currentPoint.y - content.top;
- break;
- case 5:
- scroll.x = fScrollUnit.x;
- scroll.y = -fScrollUnit.y;
- delta.x = content.right - currentPoint.x;
- delta.y = currentPoint.y - content.top;
- break;
- case 8:
- scroll.x = -fScrollUnit.x;
- delta.x = currentPoint.x - content.left;
- break;
- case 4:
- scroll.x = fScrollUnit.x;
- delta.x = content.right - currentPoint.x;
- break;
- case 10:
- scroll.x = -fScrollUnit.x;
- scroll.y = fScrollUnit.y;
- delta.x = currentPoint.x - content.left;
- delta.y = content.bottom - currentPoint.y;
- break;
- case 2:
- scroll.y = fScrollUnit.y;
- delta.y = content.bottom - currentPoint.y;
- break;
- case 6:
- scroll = fScrollUnit;
- delta.x = content.right - currentPoint.x;
- delta.y = content.bottom - currentPoint.y;
- break;
- }
-
- if (scroll != FW_kZeroPoint)
- {
- if (delta.x < FW_kFixed0)
- delta.x = FW_kFixed0;
- if (delta.y < FW_kFixed0)
- delta.y = FW_kFixed0;
-
- scroll.x = FW_RoundedToInt(((fAutoScrollInset - delta.x) * scroll.x) / fAutoScrollInset);
- scroll.y = FW_RoundedToInt(((fAutoScrollInset - delta.y) * scroll.y) / fAutoScrollInset);
-
- PrivLimitScrolling(scroll);
-
- if (delay != 0)
- {
- if (fAutoScrollStage == kOutStage)
- {
- fLastAutoScrollTick = ::FW_GetTickCount();
- fAutoScrollStage = kDelayStage;
- scroll = FW_kZeroPoint;
- }
- else if (fAutoScrollStage == kDelayStage)
- {
- if (::FW_GetTickCount() - fLastAutoScrollTick < delay)
- scroll = FW_kZeroPoint;
- else
- fAutoScrollStage = kScrollStage;
- }
- }
-
- // ----- Make sure that we don't scroll in an unwanted direction -----
- if (fScrollUnit.x == FW_kFixed0)
- scroll.x = FW_kFixed0;
- if (fScrollUnit.y == FW_kFixed0)
- scroll.y = FW_kFixed0;
- }
- else
- fAutoScrollStage = kOutStage;
- }
-
- return scroll;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScrollBy
- //----------------------------------------------------------------------------------------
- // a positive offset means we are scrolling down (down arrow)
-
- void FW_CScroller::ScrollBy(Environment* ev, const FW_CPoint& offset, FW_CGraphicContext* gc)
- {
- // ----- Validate the offset -----
- FW_CPoint scroll(offset);
- PrivLimitScrolling(scroll);
-
- PrivScrollBy(ev, scroll, gc);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScrollTo
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::ScrollTo(Environment* ev, const FW_CPoint& position, FW_CGraphicContext* gc)
- {
- ScrollBy(ev, position - fTranslation, gc);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::RevealRect
- //----------------------------------------------------------------------------------------
- // RevealRect always shows the topleft corner of rectToReveal
-
- void FW_CScroller::RevealRect(Environment* ev,
- const FW_CRect& rectToReveal,
- FW_CGraphicContext* gc)
- {
- FW_CRect boundsInContent = fFrame->GetContentView(ev)->GetBoundsInContent(ev);
- FW_CPoint extent = fFrame->GetContentView(ev)->GetExtent(ev);
-
- FW_CPoint scrollTo = boundsInContent[FW_kTopLeft];
- if (rectToReveal.left < boundsInContent.left)
- {
- scrollTo.x = rectToReveal.left;
- }
- else if (rectToReveal.right > boundsInContent.right)
- {
- scrollTo.x = rectToReveal.right - (boundsInContent.right - boundsInContent.left);
- if (scrollTo.x > rectToReveal.left)
- scrollTo.x = rectToReveal.left;
- }
-
- if (rectToReveal.top < boundsInContent.top)
- {
- scrollTo.y = rectToReveal.top;
- }
- else if (rectToReveal.bottom > boundsInContent.bottom)
- {
- scrollTo.y = rectToReveal.bottom - (boundsInContent.bottom - boundsInContent.top);
- if (scrollTo.y > rectToReveal.top)
- scrollTo.y = rectToReveal.top;
- }
-
- if (scrollTo != boundsInContent[FW_kTopLeft])
- ScrollTo(ev, scrollTo, gc);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivScrollBy
- //----------------------------------------------------------------------------------------
- // PrivScrollBy doesn't make any validation on the offset
-
- void FW_CScroller::PrivScrollBy(Environment* ev, const FW_CPoint& offset, FW_CGraphicContext* gc)
- {
- if (offset != FW_kZeroPoint)
- {
- FW_CPoint odlPos = fTranslation;
-
- // ----- I have to do that because I can't call PrivChangeFrameInternalTransform with both
- // ----- x and y changing.
- for (FW_XYSelector vhs = FW_kHorizontal; vhs <= FW_kVertical; ++vhs)
- {
- fTranslation[vhs] += offset[vhs];
- PrivChangeFrameInternalTransform(ev, odlPos, fTranslation, vhs, TRUE);
- }
-
- if (gc)
- gc->Reset();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::AutoScroll
- //----------------------------------------------------------------------------------------
- // currentPoint is in content coordinates
-
- void FW_CScroller::AutoScroll(Environment* ev,
- const FW_CPoint& currentPoint,
- FW_CGraphicContext* gc,
- unsigned long delay)
- {
- PrivScrollBy(ev, AutoScrollOffset(ev, currentPoint, delay), gc);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::HandlePageNavigationKeys
- //----------------------------------------------------------------------------------------
-
- FW_Handled FW_CScroller::HandlePageNavigationKeys(Environment* ev, const FW_CVirtualKeyEvent& theVirtualKeyEvent)
- {
- FW_Fixed pageScroll = FW_RoundedToInt(GetPageUnit(ev, FW_kVertical));
-
- FW_Handled result = FW_kHandled;
- switch (theVirtualKeyEvent.GetKeyCode(ev))
- {
- case FW_kVKPageUp:
- ScrollBy(ev, FW_CPoint(FW_kFixed0, -pageScroll));
- break;
- case FW_kVKPageDown:
- ScrollBy(ev, FW_CPoint(FW_kFixed0, pageScroll));
- break;
- case FW_kVKEnd:
- ScrollTo(ev, FW_CPoint(FW_kFixed0, fMaxTranslation[FW_kVertical]), NULL);
- break;
- case FW_kVKHome:
- ScrollTo(ev, FW_kZeroPoint, NULL);
- break;
- default:
- result = FW_kNotHandled;
- }
-
- return result;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivCreateContentScrollShape
- //----------------------------------------------------------------------------------------
- // This returns the shape (in Frame coord.) composed of the ContentView + all the views
- // scrolling in X or Y with the content.
-
- ODShape* FW_CScroller::PrivCreateContentScrollShape(Environment* ev, FW_XYSelector direction) const
- {
- FW_CSuperView* contentView = fFrame->GetContentView(ev);
- FW_ASSERT(contentView);
-
- // ----- Get the contentView first
- ODShape* scrollShape = ::FW_NewODShape(ev, FW_CRect(FW_kZeroPoint, contentView->GetSize(ev)));
- contentView->ViewToFrame(ev, scrollShape);
-
- // ----- Acquire the content scroll shape
- fFrame->PrivAcquireContentScrollShape(ev, direction, scrollShape);
-
- return scrollShape;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::Flatten
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::Flatten(Environment* ev, FW_CWritableStream& stream) const
- {
- FW_CFrame* frame = fFrame;
- #ifdef FW_DEBUG
- FW_OObjectRegistry* registry = stream.GetRegistry();
- frame = (FW_CFrame*) registry->LookupByID(ev, FW_kPreregisteredFrameObject);
- FW_ASSERT(frame == fFrame);
- #else
- FW_UNUSED(ev);
- #endif
-
- FW_WRITE_DYNAMIC_OBJECT(stream, frame, FW_CFrame);
- stream << fAutoScrollInset;
- stream << fScrollUnit;
- stream << fHandlePageNavigationKeys;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::InitializeFromStream
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::InitializeFromStream(Environment* ev, FW_CReadableStream& stream)
- {
- #ifdef FW_DEBUG
- FW_OObjectRegistry* registry = stream.GetRegistry();
- FW_CFrame* frame = (FW_CFrame*) registry->LookupByID(ev, FW_kPreregisteredFrameObject);
- FW_ASSERT(frame != 0);
- #else
- FW_UNUSED(ev);
- #endif
-
- FW_READ_DYNAMIC_OBJECT(stream, &fFrame, FW_CFrame);
- FW_ASSERT(frame == fFrame);
-
- stream >> fAutoScrollInset;
- stream >> fScrollUnit;
- stream >> fHandlePageNavigationKeys;
- }
-
- //========================================================================================
- // CLASS FW_CScrollBarScroller
- //========================================================================================
-
- FW_DEFINE_AUTO(FW_CScrollBarScroller)
- FW_DEFINE_CLASS_M1(FW_CScrollBarScroller, FW_CScroller)
-
- // This class is archivable, but we provide the archiving implementation in a separate
- // translation unit in order to enable deadstripping of the archiving-related code
- // in parts that do not use archiving with this class.
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::FW_CScrollBarScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScrollBarScroller::FW_CScrollBarScroller(Environment* ev,
- FW_CFrame* frame,
- FW_Boolean liveScrolling,
- FW_CScrollBar* horzSB,
- FW_CScrollBar* vertSB) :
- FW_CScroller(ev, frame),
- fLiveScrolling(liveScrolling)
- {
- fScrollbars[FW_kHorizontal] = horzSB;
- fScrollbars[FW_kVertical] = vertSB;
-
- PrivAttachScrollBars(ev);
-
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::FW_CScrollBarScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScrollBarScroller::FW_CScrollBarScroller(Environment* ev) :
- FW_CScroller(ev),
- fLiveScrolling(FALSE)
- {
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::~FW_CScrollBarScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScrollBarScroller::~FW_CScrollBarScroller()
- {
- FW_START_DESTRUCTOR
-
- // Don't delete the scroll bars, we don't own them! The containing view
- // or frame owns them.
-
- FW_SOMEnvironment ev;
-
- for (FW_XYSelector vhs = FW_kHorizontal; vhs <= FW_kVertical; ++vhs)
- {
- FW_CScrollBar* scrollbar = fScrollbars[vhs];
- if (scrollbar)
- {
- UnregisterScrollNotifier(ev, scrollbar);
- scrollbar->PrivAttachToScroller(ev, NULL);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::ScrollPositionChanged
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::ScrollPositionChanged(Environment* ev,
- FW_Fixed oldPos,
- FW_Fixed newPos,
- FW_XYSelector direction)
- {
- FW_CScroller::ScrollPositionChanged(ev, oldPos, oldPos, direction);
-
- FW_CScrollBar* sb = fScrollbars[direction];
- if (sb != NULL && sb->GetScrollPos(ev) != newPos)
- sb->SetScrollPos(ev, newPos);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::PrivAdjustTranslations
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::PrivAdjustTranslations(Environment* ev,
- FW_XYSelector direction,
- FW_Fixed translation,
- FW_Fixed scrollingArea)
- {
- FW_Fixed oldMax = fMaxTranslation[direction];
-
- FW_Boolean wasEnabled = fMaxTranslation[direction] > FW_kFixed0;
-
- FW_Fixed oldPos = fTranslation[direction];
- FW_CScroller::PrivAdjustTranslations(ev, direction, translation, scrollingArea);
-
- FW_Boolean isEnabled = fMaxTranslation[direction] > FW_kFixed0;
-
- FW_CScrollBar* sb = fScrollbars[direction];
- if (sb)
- {
- // ----- Update scrollbar Major and Minor scroll units
- sb->SetMinorScrollUnits(ev, FW_RoundedToInt(GetScrollUnit(ev, direction)));
- sb->SetMajorScrollUnits(ev, FW_RoundedToInt(GetPageUnit(ev, direction)));
-
- // ----- Set scrollbar maximum -----
- sb->SetScrollMax(ev, fMaxTranslation[direction]);
-
- if (fTranslation[direction] != oldPos || fMaxTranslation[direction] != oldMax)
- sb->SetScrollPos(ev, fMaxTranslation[direction], fTranslation[direction]);
-
- // [HLX] we should be able to remove that when Laurent fixes the invalidation problem
- // in SetScrollPos
- if (wasEnabled != isEnabled)
- sb->Invalidate(ev);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::RemoveScrollBar
- //----------------------------------------------------------------------------------------
- // This doesn't delete the scrollbar view itself
-
- void FW_CScrollBarScroller::RemoveScrollBar(Environment* ev, FW_XYSelector direction)
- {
- FW_UNUSED(ev);
- FW_CScrollBar* sb = fScrollbars[direction];
- if (sb == NULL)
- return;
-
- // Remove the connection first
- RemoveInterest(FW_CInterest(sb, FW_kScrollMsg));
-
- fScrollbars[direction] = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::Flatten
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::Flatten(Environment* ev, FW_CWritableStream& stream) const
- {
- FW_CScroller::Flatten(ev, stream);
-
- stream << fLiveScrolling;
-
- ODID horizScrollBarID = kODNULLID;
- ODID vertScrollBarID = kODNULLID;
-
- if (fScrollbars[FW_kHorizontal])
- horizScrollBarID = fScrollbars[FW_kHorizontal]->GetViewID(ev);
- if (fScrollbars[FW_kVertical])
- vertScrollBarID = fScrollbars[FW_kVertical]->GetViewID(ev);
-
- stream << horizScrollBarID << vertScrollBarID;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::InitializeFromStream
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::InitializeFromStream(Environment* ev, FW_CReadableStream& stream)
- {
- FW_CScroller::InitializeFromStream(ev, stream);
-
- stream >> fLiveScrolling;
-
- ODID horizScrollBarID;
- ODID vertScrollBarID;
- stream >> horizScrollBarID >> vertScrollBarID;
-
- FW_CView* hScrollBarView = NULL;
- if (horizScrollBarID != kODNULLID)
- hScrollBarView = fFrame->FindViewByID(ev, horizScrollBarID);
-
- FW_CView* vScrollBarView = NULL;
- if (vertScrollBarID != kODNULLID)
- vScrollBarView = fFrame->FindViewByID(ev, vertScrollBarID);
-
- fScrollbars[FW_kHorizontal] = FW_DYNAMIC_CAST(FW_CScrollBar, hScrollBarView);
- fScrollbars[FW_kVertical] = FW_DYNAMIC_CAST(FW_CScrollBar, vScrollBarView);
-
- PrivAttachScrollBars(ev);
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::PrivCheckFrame
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::PrivCheckFrame(Environment* ev) const
- {
- // We cannot authorize frames to use a scroller with scrollbars in case they don't have
- // a separate content view, because the scrollbars will end up moving with the rest of
- // frame's content! A frame which is its own content view can only use a basic
- // FW_CScroller instance, which can be scrolled with a hand-scrolling or auto-scrolling
- // mechanism.
-
- if (fFrame->IsContentView(ev))
- {
- FW_DEBUG_MESSAGE("Cannot use a ScrollBarScroller here, create a separate content view");
- }
-
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::PrivAttachScrollBars
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::PrivAttachScrollBars(Environment* ev)
- {
- for (FW_XYSelector vhs = FW_kHorizontal; vhs <= FW_kVertical; ++vhs)
- {
- FW_CScrollBar* scrollbar = fScrollbars[vhs];
- if (scrollbar)
- {
- RegisterScrollNotifier(ev, scrollbar);
- scrollbar->PrivAttachToScroller(ev, this);
- }
- }
- }
-